---
type: tutorial
title: 创建并传递数据到博客布局
description: >-
  教程：搭建你的 Astro 博客 -
  为你的 Markdown 文件创建一个博客文章布局，并将 frontmatter 的值作为 props 传递给布局组件。
---
import Badge from '~/components/Badge.astro';
import Box from '~/components/tutorial/Box.astro';
import Checklist from '~/components/Checklist.astro';
import PreCheck from '~/components/tutorial/PreCheck.astro';
import { Steps } from '@astrojs/starlight/components';

现在你已经为页面创建了布局，是时候为博客文章也添加一个布局了！

<PreCheck>
  - 为你的 Markdown 文件创建一个新的博客文章布局
  - 将 YAML frontmatter 的值作为 props 传递给布局组件
</PreCheck>

## 为你的博客文章编写布局

当你在一个 `.md` 文件中包含 `layout` frontmatter 属性时，你可以在布局文件中使用所有 frontmatter YAML 的值。

<Steps>
1. 创建一个新文件：`src/layouts/MarkdownPostLayout.astro`。

2. 将以下代码复制到 `MarkdownPostLayout.astro` 中。

    ```astro title="src/layouts/MarkdownPostLayout.astro"
    ---
    const { frontmatter } = Astro.props;
    ---
    <h1>{frontmatter.title}</h1>
    <p>Written by {frontmatter.author}</p>
    <slot />
    ```

3. 在 `post-1.md` 中添加以下 frontmatter 属性。

    ```markdown title="src/pages/posts/post-1.md" ins={2}
    ---
    layout: ../../layouts/MarkdownPostLayout.astro
    title: '我的第一篇博客文章'
    pubDate: 2022-07-01
    description: '这是我 Astro 博客的第一篇文章。'
    author: 'Astro 学习者'
    image:
        url: 'https://docs.astro.build/assets/full-logo-light.png'
        alt: 'The full Astro logo.'
    tags: ["astro", "blogging", "learning in public"]
    ---
    ```

4. 再次检查 `localhost:4321/posts/post-1` 上的浏览器预览，并注意布局为页面添加了什么内容。

5. 将相同的布局属性添加到你的另外两篇博客文章 `post-2.md` 和 `post-3.md` 中。在浏览器中验证你的布局是否也应用于这些文章。
</Steps>

:::tip
当使用布局时，你现在可以选择在 Markdown 内容或布局中包含元素，比如页面标题。记得亲自去检查页面预览并进行任何必要的调整，以避免重复的元素。
:::

<Box icon="puzzle-piece">

## 自己动手尝试 - 自定义博客文章布局

**挑战**：确定每篇博客文章中共有的项目，并使用 `MarkdownPostLayout.astro` 来渲染它们，而不是在 `post-1.md` 和将来的每篇博客文章中编写它们。

下面是重构你的代码的例子，将 `pubDate` 包含在布局组件中，而不是在你的 Markdown 内容的正文中编写：

```markdown title="src/pages/posts/post-1.md" del={1}
发表于：2022-07-01

欢迎来到我学习关于 Astro 的新博客！在这里，我将分享我建立新网站的学习历程。
```

```astro title="src/layouts/MarkdownPostLayout.astro" ins={5}
---
const { frontmatter } = Astro.props;
---
<h1>{frontmatter.title}</h1>
<p>发表于： {frontmatter.pubDate.toString().slice(0,10)}</p>
<p>Written by {frontmatter.author}</p>
<slot />
```

根据你认为的有用程度进行重构，并根据需要向布局中添加更多内容。记住，你添加到布局中的每一项都会减少你在每篇博客文章中需要编写的内容！

下面是一个重构后的布局示例，只留下了由 slot 渲染的单个博客文章内容。你可以自由使用这个示例，或者创建自己的布局！

```astro title="src/layouts/MarkdownPostLayout.astro"
---
const { frontmatter } = Astro.props;
---
<h1> {frontmatter.title}</h1>
<p>{frontmatter.pubDate.toString().slice(0,10)}</p>
<p><em>{frontmatter.description}</em></p>
<p>Written by: {frontmatter.author}</p>
<img src={frontmatter.image.url} width="300" alt={frontmatter.image.alt} />
<slot />
```
</Box>

:::note[避免重复]
由布局渲染的任何内容都**不需要**在你的博客文章中再写一遍！如果在检查浏览器预览时注意到任何重复的内容，请确保从 Markdown 文件中删除它。
:::

<Box icon="question-mark">

### 检验你的知识

你能找出应该填入空白处的内容，使得以下两个组件一起产生可用的 Astro 代码吗？

1.  ```markdown title="src/pages/posts/learning-astro.md"
    ---
    layout: ../../__________/MyMarkdownLayout.astro
    title: "Learning About Markdown in Astro"
    author: Astro Learner
    ____: 2022-08-08
    ---
    I learned so much today! Astro allows me to write in Markdown, but also use variables from the frontmatter. I can even access those values in an Astro layout component.
    ```

2.  ```astro title="src/layouts/MarkdownLayout.astro"
    ---
    import ____________ from '../components/Footer.astro'
    const { ___________ } = Astro.props
    ---
    <h1>{frontmatter.title}</h1>
    <p>Written by:{frontmatter.______ } on {frontmatter.pubDate}</p>
    < _______ />
    <Footer />
    ```
    <details>
        <summary>显示填写好空白处的代码！</summary>

        1.  ```markdown title="src/pages/posts/learning-astro.md" "../layouts" "pubDate:"
            ---
            layout: ../../layouts/MyMarkdownLayout.astro
            title: "Learning About Markdown in Astro"
            author: Astro Learner
            pubDate: 2022-08-08
            ---
            I learned so much today! Astro allows me to write in Markdown, but also use variables from the frontmatter. I can even access those values in an Astro layout component.
            ```

        2.  ```astro title="src/layouts/MarkdownLayout.astro" " Footer " " frontmatter " ".author" "slot"
            ---
            import Footer from '../components/Footer.astro'
            const { frontmatter } = Astro.props
            ---
            <h1>{frontmatter.title}</h1>
            <p>Written by:{frontmatter.author } on {frontmatter.pubDate}</p>
            <slot />
            <Footer />
            ```
    </details>
</Box>

<Box icon="check-list">

## 任务清单

<Checklist>
- [ ] 我可以在 YAML frontmatter 中为 Markdown 博客文章添加布局属性。
- [ ] 我可以为 Markdown 文章创建一个单独的布局。
- [ ] 我可以在布局组件中使用博客文章的 frontmatter 值。
</Checklist>

</Box>

### 相关资源

- [Astro 中的 Markdown 布局](/zh-cn/guides/markdown-content/#frontmatter-layout)
- [Markdown 布局属性](/zh-cn/basics/layouts/#markdown-布局的-props)
- [YAML 介绍](https://dev.to/paulasantamaria/introduction-to-yaml-125f) <Badge>外部链接</Badge>
